#include "Libraries/MissionSystemFL.h"
#include "Component/MissionComponent.h"
#include "GameFramework/Actor.h"
#include "Engine/World.h"
#include "Data/BaseData.h"
#include "Kismet/GameplayStatics.h"
#include "Data/PlayerControllerInterface.h"
#include "Actor/TargetsManager.h"

UMissionComponent* UMissionSystemFL::GetMissionComponent()
{
	APlayerController* PlayerController = UGameplayStatics::GetPlayerController(GWorld, 0);
	if (PlayerController) {
		APawn* Player = PlayerController->GetPawn();
		if (Player&&Player->IsLocallyControlled()&&Player->IsPawnControlled()) {
			GetInterfacePtr(IPlayerControllerInterface, PlayerControllerInterface, PlayerController);
			if (PlayerControllerInterface) {
				UMissionComponent* LocTemp = PlayerControllerInterface->RequestMissionComponent();
				if (LocTemp) return LocTemp;
			}
		}
	}
	return nullptr;
}

bool UMissionSystemFL::IsLocalPawn(AActor* Pawn)
{
	APawn* Player = Cast<APawn>(Pawn);
	if (Player) {
		return Player->IsLocallyControlled() && Player->IsPawnControlled();
	}
	return false;
}

ATargetsManager* UMissionSystemFL::GetTargetManager()
{
	TArray<AActor*> OutActors;
	UGameplayStatics::GetAllActorsOfClass(GWorld, ATargetsManager::StaticClass(), OutActors);
	if (OutActors[0]->IsValidLowLevel()) {
		ATargetsManager* TargetsManager = Cast<ATargetsManager>(OutActors[0]);
		if (TargetsManager)
			return TargetsManager;
	}
	return nullptr;
}

FTargetInfo UMissionSystemFL::FindInCurrentTargets(const FName& WithUniqueName)
{
	FTargetInfo Loc;
	ATargetsManager* TargetsManager = GetTargetManager();
	for (const FTargetInfo& Elem : TargetsManager->Targets) {
		if (Elem.TargetUniqueName == WithUniqueName) {
			Loc = Elem;
			break;
		}
	}
	return Loc;
}

void UMissionSystemFL::MissionComponentOnOverlap(AActor* OtherActor, bool& OutCanAccess, UMissionComponent*& OutComponentReference)
{
	APawn* Player = Cast<APawn>(OtherActor);
	if (Player) {
		if (Player->GetController()->IsValidLowLevel()&&
			Player->GetController()->IsLocalController() && 
			Player->GetController()->IsLocalPlayerController()) 
		{
			GetInterfacePtr(IPlayerControllerInterface, PlayerControllerInterface, Player->GetController());
			if (PlayerControllerInterface) {
				UMissionComponent* MissionComponent=PlayerControllerInterface->RequestMissionComponent();
				if (MissionComponent->IsValidLowLevel()) {
					OutCanAccess = true;
					OutComponentReference = MissionComponent;
					return;
				}
			}
		}
	}
	OutCanAccess = false;
	OutComponentReference = nullptr;
	return;
}

bool UMissionSystemFL::IsTargetInCurrentObjectives(const FName& TargetUniqueName)
{
	bool LocisInObjectives = false;
	UMissionComponent* MissionComponent = GetMissionComponent();
	if (MissionComponent) {
		for (const auto& Elem : MissionComponent->CurrentObjectives) {
			switch (Elem.ObjectiveClass)
			{
			case  EObjectiveLType::Select:
				break;
			case  EObjectiveLType::MultipleTargets:
				for (const auto& elem : Elem.ObjectiveTargets) {
					if (elem.TargetsUniqueName == TargetUniqueName) {
						LocisInObjectives = true;
						break;;
					}	
					else LocisInObjectives = false;
				}
				break;
			case  EObjectiveLType::SingleTarget:
				if (Elem.ObjectiveTargets[0].TargetsUniqueName == TargetUniqueName)
					LocisInObjectives = true;
				else LocisInObjectives = false;
				break;
			}
		}
	}
	return MissionComponent->InMission&&LocisInObjectives;
}

bool UMissionSystemFL::IsInSpecificMission(const FName& UniqueMissionName)
{
	UMissionComponent* MissionComponent = GetMissionComponent();
	if (MissionComponent) {
		FString MissionName = MissionComponent->CurrentMission.MissionMainInfo.Name.ToString();
		return MissionComponent->InMission&&FName(*MissionName)== UniqueMissionName;
	}
	else return false;
}

bool UMissionSystemFL::IsInMission()
{
	UMissionComponent* MissionComponent = GetMissionComponent();
	if (MissionComponent) {
		return MissionComponent->InMission;
	}
	else return false;
}
